package de.hauschild.orbitvm.vm.instruction.impl.single;

import de.hauschild.orbitvm.vm.VM;
import de.hauschild.orbitvm.vm.instruction.impl.AbstractInstruction;

/**
 * A abstract extension ob {@link AbstractInstruction} providing basic funtionality for single instructions.
 * 
 * @since 1.0.0
 * @author Klaus Hauschild
 */
public abstract class AbstractSingleInstruction extends AbstractInstruction {

  private final int argumentAdress;

  /**
   * Instantiates a new {@link AbstractSingleInstruction}.
   * 
   * @param theInstructionCounter
   *          the the instruction counter
   * @param theArgumentAddress
   *          the the argument address
   */
  public AbstractSingleInstruction(final int theInstructionCounter, final int theArgumentAddress) {
    super(theInstructionCounter);
    argumentAdress = theArgumentAddress;
  }

  @Override
  public void evaluate(final VM vm) {
    vm.getMemory()[getInstructionCounter()] = evaluate(vm.getMemory()[argumentAdress]);
  }

  @Override
  public String toString() {
    return String.format("%d: %s (%d)", getInstructionCounter(), getName(), argumentAdress);
  }

  /**
   * Evaluates the given argument.
   * 
   * @param argument
   *          the argument
   * @return the double
   */
  protected abstract double evaluate(final double argument);

  /**
   * Gets the name.
   * 
   * @return the name
   */
  protected abstract String getName();

}
